Skip to content

Conversation

@RomaKis
Copy link
Contributor

@RomaKis RomaKis commented Nov 10, 2017

ProductRepository fails to load product with camelcase SKU

Fixed Issues (if relevant)

  1. ProductRepository fails to load product with camelcase SKU #12073: ProductRepository fails to load product with camelcase SKU

Manual testing scenarios

  1. Create a simple product with the camel case sku (for example "Test")
  2. Use get() method of \Magento\Catalog\Model\ProductRepository to get this product by sku, and specify the sku in lower case.

Expected result

  1. NoSuchEntityException is returned

Contribution checklist

  • Pull request has a meaningful description of its purpose
  • All commits are accompanied by meaningful commit messages
  • All new or changed code is covered with unit/integration tests (if applicable)
  • All automated tests passed successfully (all builds on Travis CI are green)

@magento-engcom-team magento-engcom-team added Reproduced on 2.2.x The issue has been reproduced on latest 2.2 release Reproduced on 2.3.x The issue has been reproduced on latest 2.3 release labels Nov 10, 2017
@ishakhsuvarov ishakhsuvarov self-assigned this Nov 10, 2017
@ishakhsuvarov ishakhsuvarov added this to the November 2017 milestone Nov 10, 2017
}

if (!isset($this->instances[$sku])) {
throw new NoSuchEntityException(__('Requested product doesn\'t exist'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code completely duplicates previous condition.

What is this issue all about? I see a trim but don't see any strtolower in logic like $this->instances[$product->getSku()][$cacheKey] = $product;.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orlangur, ok, let me explain. We have product with sku "Test". We try to use "get" method of repository to get product with sku "test". Method resourceModel->getIdBySku($sku) will return to us id of "Test" and in $this->instances it put the sku "Test". So after trim we are checking if we have $this->instances["test"] and we don't have it, because we have $this->instances["Test"].

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orlangur, what how? Trimming isn't my logic). It was before my changes. I only check if product sku("Test") is the same as requested sku("test"). And if it isn't the same exception will be thrown.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, let me reword. Why product is stored with lower-cased SKU in the first place?

We must find a root cause so that exception will be thrown from line 240 instead of adding more exceptions throwing.

@RomaKis
Copy link
Contributor Author

RomaKis commented Dec 14, 2017

@orlangur, any updates on it?

@RomaKis
Copy link
Contributor Author

RomaKis commented Jan 3, 2018

@orlangur, ping.

@okorshenko okorshenko modified the milestones: December 2017, January 2018 Jan 8, 2018
}

if (!isset($this->instances[$sku])) {
throw new NoSuchEntityException(__('Requested product doesn\'t exist'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, let me reword. Why product is stored with lower-cased SKU in the first place?

We must find a root cause so that exception will be thrown from line 240 instead of adding more exceptions throwing.

@erikhansen
Copy link
Contributor

For the record, this PR will not fix the issue that it purports to fix (#12073). It will simply result in an exception rather than an error if the condition described in #12073 is met. However it will not allow a SKU with a mixed-case to get loaded via the product repository.

See this comment for more context.

@orlangur
Copy link
Contributor

@erikhansen,

this PR will not fix the issue that it purports to fix (#12073)

Expected result
NoSuchEntityException is returned

Actually, not, but I do agree with comment you referring to that it is better to fix regression introduced.

Copy link
Contributor

@orlangur orlangur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RomaKis,

It's a regression in 2.2.0, still present as of 2.2.2. The problem was introduced right here: cb3b5d1#diff-ff4893a5628d34910295bae32fbcddfdL241

Just change implementation of cacheProduct in such a way that we pass both productId and sku instead of obtaining them from product instance.

The test should enforce that we can actually load product by such SKU.

@RomaKis
Copy link
Contributor Author

RomaKis commented Feb 26, 2018

@orlangur

Just change implementation of cacheProduct in such a way that we pass both productId and sku instead of obtaining them from product instance.

This sounds obscure, because we have two different functions get() and getById() which have only sku or only id as argument. Or do you mean to create two separate methods cacheBySku and cacheById ? In that way product will be cashed after first load only by by id or only by sku, but not by both.
Also I think this is not good idea, because we can ask product by sku test and Test. First it will cache it with the key test and the second time it will cache it again with the key Test, so we will have two same products in cache with different keys.

@okorshenko okorshenko modified the milestones: February 2018, March 2018 Mar 1, 2018
@orlangur
Copy link
Contributor

orlangur commented Mar 9, 2018

@RomaKis,

so we will have two same products in cache with different keys.

That's the point. It should work this way.

Just rework implementation of cacheProduct in cb3b5d1#diff-ff4893a5628d34910295bae32fbcddfdL241 so that code behavior remain unchanged.

@RomaKis
Copy link
Contributor Author

RomaKis commented Mar 9, 2018

@orlangur, Why do we need to cache "test" and "Test" if we have only only one product? It is obscure. This is misleading and I don't think this is right.
I think we have two ways to resolve this issue:

  1. make all skus strtolower();
  2. throw exception if request sku is wrong.

@orlangur
Copy link
Contributor

orlangur commented Mar 9, 2018

It is obscure. This is misleading and I don't think this is right.

Please reword a bit. strtolower implementation is a bit fragile and counter-intuitive. Proposed approach does not lead to any negative side effect as there is already mechanism to prevent cache overflow.

@RomaKis
Copy link
Contributor Author

RomaKis commented Mar 12, 2018

You are right that strtolower isn't a good solution.

So, I think it should throw exception. If I have product with sku "Test", so why when I ask product with sku "teSt" it should return the same product? We don't have product with sku "teSt", we have only with sku "Test". This is misleading for me.

@orlangur
Copy link
Contributor

@RomaKis because that's how it worked before we introduced caching in product repository.

Another case I didn't mention is that MySQL does not distinguish not just lower/upper case but also е and ё, o and ö, a and ã and so on.

There is no need to introduce any additional restrictions if we can keep the things consistent without them.

@RomaKis
Copy link
Contributor Author

RomaKis commented Mar 14, 2018

If it worked in such way it didn't mean that it worked right. I remain at my mind - Magento shouldn't cache products with non-existent sku. As I mentioned it is misleading.

You can SELECT from SQL case sensitive with BINARY.

If you don't accept this implementation - so close this PR )

@orlangur
Copy link
Contributor

Such case is not nonexistent SKU in fact and is a behavior explicitly requested in #12169 (comment).

@mcspronko
Copy link
Contributor

mcspronko commented Jul 23, 2018

@orlangur What is the reason for rejecting the pull request? The issue is from Nov 2017 and still not fixed. Is there a plan in place to address this issue or it is up to the community and their availability to fix it?

@orlangur
Copy link
Contributor

orlangur commented Aug 2, 2018

@mcspronko because a proper implementation approach is performed in #14019. It needs some assistance with test but no time to look into it yet.

Cc: @maximgubar

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Progress: needs update Progress: reject Release Line: 2.2 Reproduced on 2.2.x The issue has been reproduced on latest 2.2 release Reproduced on 2.3.x The issue has been reproduced on latest 2.3 release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants